/**
 * chenuu.com
 * 
 * @author  zhaoxu.com@gmail.com
 * @created 2012-11-10
 */
package com.chenuu.integration.httpclient.dropbox;

import com.dropbox.client2.jsonextract.JsonExtractionException;
import com.dropbox.client2.jsonextract.JsonList;
import com.dropbox.client2.jsonextract.JsonThing;

/**
 * A single entry in a {@link DeltaPage DeltaPage}.
 */
public class DeltaEntry<MD> {
    /**
     * The lower-cased path of the entry.  Dropbox compares file paths in a
     * case-insensitive manner.  For example, an entry for <code>"/readme.txt"</code>
     * should overwrite the entry for <code>"/ReadMe.TXT"</code>.
     *
     * <p>
     * To get the original case-preserved path, look in the {@link #metadata metadata} field.
     * </p>
     */
    public final String lcPath;

    /**
     * If this is <code>null</code>, it means that this path doesn't exist on
     * on Dropbox's copy of the file system.  To update your local state to
     * match, delete whatever is at that path, including any children.
     * If your local state doesn't have anything at this path, ignore this entry.
     *
     * <p>
     * If this is not <code>null</code>, it means that Dropbox has a file/folder
     * at this path with the given metadata.  To update your local state to match,
     * add the entry to your local state as well.
     * </p>
     * <ul>
     * <li>
     *     If the path refers to parent folders that don't exist yet in your local
     *     state, create those parent folders in your local state.
     * </li>
     * <li>
     *     If the metadata is for a file, replace whatever your local state has at
     *     that path with the new entry.
     * </li>
     * <li>
     *     If the metadata is for a folder, check what your local state has at the
     *     path.  If it's a file, replace it with the new entry.  If it's a folder,
     *     apply the new metadata to the folder, but do not modify the folder's
     *     children.
     * </li>
     * </ul>
     */
    public final MD metadata;

    public DeltaEntry(String lcPath, MD metadata) {
        this.lcPath = lcPath;
        this.metadata = metadata;
    }

    public static final class JsonExtractor<MD> extends com.dropbox.client2.jsonextract.JsonExtractor<DeltaEntry<MD>> {
        public final com.dropbox.client2.jsonextract.JsonExtractor<MD> mdExtractor;

        public JsonExtractor(com.dropbox.client2.jsonextract.JsonExtractor<MD> mdExtractor) {
            this.mdExtractor = mdExtractor;
        }

        public DeltaEntry<MD> extract(JsonThing j) throws JsonExtractionException {
            return extract(j, this.mdExtractor);
        }

        public static <MD> DeltaEntry<MD> extract(JsonThing j, com.dropbox.client2.jsonextract.JsonExtractor<MD> mdExtractor) throws JsonExtractionException {
            JsonList l = j.expectList();
            String path = l.get(0).expectString();
            MD metadata = l.get(1).optionalExtract(mdExtractor);
            return new DeltaEntry<MD>(path, metadata);
        }
    }

}
